package com.gxa.eshop.portal.listener;

import com.gxa.eshop.core.exception.BusinessException;
import com.gxa.eshop.portal.service.GoodsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.activemq.command.ActiveMQObjectMessage;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import java.io.Serializable;


@Component
@Slf4j
public class GoodsCacheListener  {

    @Resource
    GoodsService goodsService;

    @Resource
    RedisTemplate redisTemplate;

    /**
     *
     * @param message Message类型的参数,除了包含消息正文之外,还会包含消息签收功能
     * @param session
     * @throws BusinessException
     */
    @JmsListener(destination = "goodsCache",containerFactory = "simpleFactory")
    public synchronized void listen(Message message, Session session) {

        // 事务: 保证发送的完整性
        // 签收 : 消息的可靠性

//        使用捕获方式处理异常, 方便消息的重新发送(运行时异常的消息的重发机制)
        try {
            boolean transacted = session.getTransacted();
            int acknowledgeMode = session.getAcknowledgeMode();
          //  System.out.println("transacted:"+transacted);    //transacted: true
          //  System.out.println("acknowledgeMode:"+acknowledgeMode); // acknowledgeMode: 0

            // 从缓存中删除该id对应的数据
            // 获取id的方法是通过将Message向下转型,转为ActiveMQObjectMessage
            // 利用getObject() 方法
            Serializable id = ((ActiveMQObjectMessage) message).getObject();

            log.info("从goodsCache中收到的id:{}",id);

            // 从redis中判断是否已经存在, 存在表示已经消费过,
            // 如果已经消费过,则直接签收, 跳过后续业务
            Object goodsCacheMQ = redisTemplate.opsForHash().get("goodsCacheMQ:", message.getJMSMessageID());
            if(!StringUtils.isEmpty(goodsCacheMQ)){
                // 满足条件即表示消费过
                // 应该马上手动签收
                message.acknowledge();
                return;  // 离开方法
            }

            goodsService.removeGoodsCache(Long.valueOf(id.toString()));
            // 把id存入到redis
            redisTemplate.opsForHash().put("goodsCacheMQ:",message.getJMSMessageID(),"1");


            // 最后执行签收操作
            message.acknowledge();
        } catch (JMSException e) {

            log.error(e.getMessage());

            // 当出现异常的时候, 消息无法签收, MQ应该重新发送
            // 利用RuntimeException异常的抛出重发机制(MQ)
            throw new RuntimeException(e);
        }
    }
}
